package fr.bugtracker.commun.outils;

import java.util.List;

import org.apache.log4j.Logger;

import fr.bugtracker.commun.enumeration.EnumLoggerLevel;
import fr.bugtracker.commun.enumeration.EnumLogger;

/**
 * Classe utilitaire pour les logs
 * @author Laurent
 * @version 0.1
 */
public abstract class UtilsLogger {

	/**
	 * Symbole utilisé pour les messages de type titre
	 */
	public final static String SYMBOLE_TITRE = "----->";
	/**
	 * package de l'application
	 */
	private final static String PACKAGE_APPLICATION = "fr.bugtracker.";

	/**
	 * Constructeur de la classe <code>UtilsLogger</code>.
	 */
	private UtilsLogger() {
	}

	/**
	 * Retourne le login formatté
	 * @param pLogApplication boolean
	 * @return {@link String}
	 */
	private static String getLoginFormatte(boolean pLogApplication) {
		if (UtilsAuthentication.getUtilisateurSession() != null) {
			return UtilsAuthentication.getUtilisateurSession().getUsername();
		}
		return "-";
	}

	/**
	 * Loggue le message
	 * @param pLogger {@link EnumLogger}
	 * @param pTitre boolean
	 * @param pLevel {@link EnumLoggerLevel}
	 * @param pLogApplication boolean
	 * @param pMessage {@link String}
	 * @param pParameters {@link String}...
	 */
	private static void logguer(EnumLogger pLogger, boolean pTitre, EnumLoggerLevel pLevel, boolean pLogApplication, String pMessage, String... pParameters) {
		String vMessage;
		if (pTitre) {
			if (!pLogApplication) {
				vMessage = String.format("%s %s (%s)", SYMBOLE_TITRE, UtilsMetier.getMessage(pMessage, pParameters), getLoginFormatte(pLogApplication));
			} else {
				vMessage = String.format("%s %s", SYMBOLE_TITRE, UtilsMetier.getMessage(pMessage, pParameters));
			}
		} else {
			vMessage = UtilsMetier.getMessage(pMessage, pParameters);
		}
		switch (pLevel) {
		case debug:
			Logger.getLogger(pLogger.name()).debug(vMessage);
			break;
		case info:
			Logger.getLogger(pLogger.name()).info(vMessage);
			break;
		case warning:
			Logger.getLogger(pLogger.name()).warn(vMessage);
			break;
		case error:
			Logger.getLogger(pLogger.name()).error(vMessage);
			break;
		default:
			break;
		}
	}

	/**
	 * Crée un log fonctionnel d'une seule ligne de titre
	 * @param pLevel {@link EnumLoggerLevel}
	 * @param pLogApplication boolean
	 * @param pMessage {@link String}
	 * @param pParameters {@link String}...
	 */
	public static void logFonctionnel(EnumLoggerLevel pLevel, boolean pLogApplication, String pMessage, String... pParameters) {
		logguer(EnumLogger.fonctionnel, true, pLevel, pLogApplication, pMessage, pParameters);
	}

	/**
	 * Crée un log fonctionnel de plusieurs lignes dont la première est une ligne de titre
	 * @param pLevel {@link EnumLoggerLevel}
	 * @param pLogApplication boolean
	 * @param pListeMessage {@link List}< {@link String} >
	 */
	public static void logFonctionnel(EnumLoggerLevel pLevel, boolean pLogApplication, List<String> pListeMessage) {
		for (int i = 0; i < pListeMessage.size(); i++) {
			if (i == 0) {
				logguer(EnumLogger.fonctionnel, true, pLevel, pLogApplication, pListeMessage.get(i));
			} else {
				logguer(EnumLogger.fonctionnel, false, pLevel, pLogApplication, pListeMessage.get(i));
			}
		}
	}

	/**
	 * Crée un log technique d'une seule ligne de titre
	 * @param pLevel {@link EnumLoggerLevel}
	 * @param pLogApplication boolean
	 * @param pMessage {@link String}
	 * @param pParameters {@link String}...
	 */
	public static void logTechnique(EnumLoggerLevel pLevel, boolean pLogApplication, String pMessage, String... pParameters) {
		logguer(EnumLogger.technique, true, pLevel, pLogApplication, pMessage, pParameters);
	}

	/**
	 * Crée un log technique de plusieurs lignes dont la première est une ligne de titre
	 * @param pLevel {@link EnumLoggerLevel}
	 * @param pLogApplication boolean
	 * @param pListeMessage {@link List}< {@link String} >
	 */
	public static void logTechnique(EnumLoggerLevel pLevel, boolean pLogApplication, List<String> pListeMessage) {
		for (int i = 0; i < pListeMessage.size(); i++) {
			if (i == 0) {
				logguer(EnumLogger.technique, true, pLevel, pLogApplication, pListeMessage.get(i));
			} else {
				logguer(EnumLogger.technique, false, pLevel, pLogApplication, pListeMessage.get(i));
			}
		}
	}

	/**
	 * Loggue l'exception dans le fichier technique
	 * @param pException {@link Throwable}
	 */
	public static void logException(Throwable pException) {
		while (pException.getCause() != null) {
			pException = pException.getCause();
		}
		logguer(EnumLogger.technique, true, EnumLoggerLevel.error, true, String.format("[%s] %s", pException.getClass(), pException.getMessage()));
		for (StackTraceElement vStack : pException.getStackTrace()) {
			if (vStack.getClassName().startsWith(PACKAGE_APPLICATION)) {
				logguer(EnumLogger.technique, false, EnumLoggerLevel.error, true, vStack.toString());
			}
		}
	}

	/**
	 * Affiche un message dans la console
	 * @param pValeurs {@link Object}...
	 */
	public static void debug(Object pValeurs) {
		Logger.getLogger(EnumLogger.console.name()).debug(pValeurs);
	}

}
